package cn.stylefeng.guns.modular.gridsystem.utils;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Stream;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.stylefeng.guns.core.context.constant.ConstantContextHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ssy
 * @date 2022/3/31 9:41
 */
public class MyFileUtils {

    private static final Logger logger = LoggerFactory.getLogger(MyFileUtils.class);

    /**
     * 获取上传路径
     * @return
     */
    public static String getUploadPath(){
        //动态获取环境变量的值；Windows 10
        String property = System.getProperties().getProperty("os.name");

        //获取音频文件
        String path;
        if(property.contains("Windows")){
            path =  ConstantContextHolder.getDefaultFileUploadPathForWindows();
        }else {
            path = ConstantContextHolder.getDefaultFileUploadPathForLinux();
        }
        return path;
    }

    /**
     * @Title: byteToFile
     * @Description: 把二进制数据转成指定后缀名的文件，例如PDF，PNG等
     * @param contents 二进制数据
     * @param filePath 文件存放目录，包括文件名及其后缀，如D:\file\bike.jpg
     */
    public static void byteToFile(byte[] contents, String filePath) {
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        BufferedOutputStream output = null;
        try {
            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(contents);
            bis = new BufferedInputStream(byteInputStream);
            File file = new File(filePath);
            // 获取文件的父路径字符串
            File path = file.getParentFile();
            if (!path.exists()) {
                logger.info("文件夹不存在，创建。path={}", path);
                boolean isCreated = path.mkdirs();
                if (!isCreated) {
                    logger.error("创建文件夹失败，path={}", path);
                }
            }
            fos = new FileOutputStream(file);
            // 实例化OutputString 对象
            output = new BufferedOutputStream(fos);
            byte[] buffer = new byte[1024];
            int length = bis.read(buffer);
            while (length != -1) {
                output.write(buffer, 0, length);
                length = bis.read(buffer);
            }
            output.flush();
        } catch (Exception e) {
            logger.error("输出文件流时抛异常，filePath={}", filePath, e);
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (fos != null) {
                    fos.close();
                }
                if (output != null) {
                    output.close();
                }
            } catch (IOException e0) {
                logger.error("文件处理失败，filePath={}", filePath, e0);
            }
        }
    }

    /**
     * 根据占用百分比删除文件
     * @param homePath 计算空间占用的文件夹路径
     * @param directoryPath 删除文件的文件夹路径
     * @param diskThreshold homePath空间占比多少开始删除文件
     * @param deleteFileRatio 删除文件数量占比（directoryPath中的文件数量为总数）
     */
    public static void cleanupFilesByPercentum(String homePath, String directoryPath, double diskThreshold,double deleteFileRatio) {
        File homeDirectory = new File(homePath);
        Path directory = Paths.get(directoryPath);

        if (!Files.exists(directory)) {
            logger.error("百分比删除文件失败，目录不存在：{}", directory);
            return;
        }

        double diskUsage = (double) (homeDirectory.getTotalSpace() - homeDirectory.getFreeSpace()) / homeDirectory.getTotalSpace();

        if (diskUsage >= diskThreshold) {

            File folder = new File(directoryPath);
            List<File> files = loopFiles(folder);
            files.sort(Comparator.comparingLong(File::lastModified));
            files.stream().limit((long) (files.size() * deleteFileRatio)).forEach(file -> {
                boolean deleteSuccess = file.delete();
                if (deleteSuccess) {
                    logger.info(file.getPath() + "删除成功");
                } else {
                    logger.info(file.getPath() + "删除失败");
                }
            });

        }
    }


    /**
     * 删除指定文件夹指定天数以前的文件
     * @param directoryPath
     * @param daysThreshold
     */
    public static void cleanupFiles(String directoryPath, int daysThreshold) {
        Path directory = Paths.get(directoryPath);
        if (!Files.exists(directory)) {
            logger.error("删除文件指定天数文件目录失败，目录不存在：{}", directory);
            return;
        }

        File folder = new File(directoryPath);
        List<File> files = loopFiles(folder);
        for (File file : files){
            if (file.isFile() && file.lastModified() < System.currentTimeMillis() - ((long) daysThreshold * 24 * 60 * 60 * 1000)) {
                boolean deleteSuccess = file.delete();
                if (deleteSuccess) {
                    logger.info(file.getPath() + "删除成功");
                } else {
                    logger.info(file.getPath() + "删除失败");
                }
            }
        }
    }

    /**
     * 获取文件夹下的文件列表
     * @param filePath
     * @return
     */
    private static List<File> loopFiles(File filePath){
        List<File> list = new ArrayList<>();
        File[] files = filePath.listFiles();
        if (files != null) {
            for(File file:files){
                if(file.isDirectory()){
                    list.addAll(loopFiles(file));
                }
                if(file.isFile()){
                    list.add(file);
                }
            }
        }
        return list;
    }

}
